/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 abstract_combat_object.h

	$Header: /heroes4/abstract_combat_object.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( ABSTRACT_COMBAT_OBJECT_H_INCLUDED )
#define ABSTRACT_COMBAT_OBJECT_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <list>
#include "abstract_bitmap_typedef.h"
#include "battlefield_metrics.h"
#include "combat_object_base.h"
#include "combat_object_list.h"
#include "combat_saveable_object.h"
#include "handler.h"
#include "map_point.h"
#include "sized_int_types.h"

class   t_attackable_object;
class   t_battlefield;
class	t_battlefield_reader;
class   t_combat_action_message;
class   t_combat_creature;
class	t_combat_footprint;
class   t_combat_object_fader;
class	t_combat_object_visitor;
class   t_compound_object;
enum    t_direction;
struct	t_screen_point;
struct	t_screen_rect;


// -----------------------------------------------------------------------
// t_abstract_combat_object class
// -----------------------------------------------------------------------

class t_abstract_combat_object : public t_combat_saveable_object, public t_combat_object_base
{
public:
	// Member functions
	t_abstract_combat_object( t_battlefield* battlefield );

	virtual bool                blocks_movement() const;
	void                        clear_fader();
	virtual void				draw_shadow_to(
									t_uint32				current_time,
									t_screen_rect const &	source_rect,
									t_abstract_bitmap16 &	dest,
									t_screen_point const &	dest_point ) const = 0;
	virtual void				draw_shadow_to(
									t_uint32				current_time,
									t_abstract_bitmap16 &	dest,
									t_screen_point const &	dest_point ) const = 0;
	virtual void				draw_to(
									t_uint32				current_time,
									t_screen_rect const &	source_rect,
									t_abstract_bitmap16 &	dest,
									t_screen_point const &	dest_point ) const = 0;
	virtual void				draw_to(
									t_uint32				current_time,
									t_abstract_bitmap16 &	dest,
									t_screen_point const &	dest_point ) const = 0;
	void                        fade_in( t_battlefield& battlefield, int max_alpha, t_combat_action_message const & message );
	void						fade_out( t_battlefield& battlefield, t_combat_action_message const & message );
	void						fade_out( t_battlefield& battlefield, t_handler handler, t_combat_action_message const & message );
	int                         get_alpha() const;
	virtual t_attackable_object* get_attackable_object();
	long						get_battlefield_id() const;
	virtual t_compound_object*  get_compound_object() const;
	virtual int					get_depth() const;
	virtual int					get_height() const = 0;
	t_combat_object_iterator	get_list_position();
	virtual int					get_normal_alpha() const;
	int                         get_maximum_alpha() const;
	virtual t_screen_rect		get_rect() const = 0;
	virtual t_screen_rect		get_rect( t_uint32 current_time ) const = 0;
	t_screen_point const&		get_screen_position() const;				
	t_screen_point const&		get_shadow_screen_point() const;
	virtual t_screen_rect		get_shadow_rect() const = 0;
	virtual t_screen_rect		get_shadow_rect( t_uint32 current_time ) const = 0;
	t_screen_rect const&		get_shadow_view_rect() const;
	t_screen_rect const&		get_view_rect() const;
	virtual t_combat_object_type	get_object_type() const = 0;
	virtual bool				hinders_movement() const;
	virtual bool				hit_test( t_uint32				current_time,
										  t_screen_point const &	point ) const = 0;
	virtual bool				is_animated() const = 0;
	virtual bool				is_elevated() const;
	bool						is_fading() const;
	bool						is_on_draw_list() const;
	virtual bool				is_quicksand() const;
	virtual bool				is_underlay() const = 0;
	void						move( t_battlefield&		battlefield, 
		                              t_map_point_3d const& new_position );
	virtual	bool				obscures_vision() const;
	virtual void				on_battlefield_destruction();
	virtual void                on_moved( bool cell_changed );
	virtual void                on_moving();
	virtual void                on_placed();
	virtual void                on_removed();
	virtual void                on_turned();
	virtual void                on_turning();
	virtual void				place_during_read( t_battlefield& battlefield );
	virtual bool				needs_redrawing( t_uint32	last_update_time,
											     t_uint32	current_time ) const = 0;
	virtual void				set_alpha( t_battlefield& battlefield, int arg );
	void						set_list_position( t_combat_object_iterator position );
	void                        set_maximum_alpha( int arg = 15 );
	void						set_on_draw_list( bool arg );
	void						set_screen_position( t_screen_point const& point );
	void                        set_shadow_displacement( int arg,
		                                                 t_battlefield const& battlefield );
	void						set_shadow_view_rect( t_screen_rect const& rect );
	void						set_view_rect( t_screen_rect const& rect );
protected:
	bool read_data( std::streambuf& stream );
	bool write_data( std::streambuf& stream ) const;

	// Changes in depth for overlays, underlays, etc
	enum t_depth_adjustment
	{
		k_depth_overlay = -10000, // Combat labels
		k_depth_shader = +10000,  // t_combat_area_shader
		k_depth_underlay = +20000 // underlays
	};

private:
	typedef t_counted_ptr<t_combat_object_fader> t_fader_ptr;

	// Data members
	int							m_alpha;
	long						m_battlefield_id;
	t_fader_ptr					m_fader;
	t_combat_object_iterator	m_list_position;
	int							m_maximum_alpha;
	bool						m_on_draw_list;
	t_screen_point				m_screen_position;
	int							m_shadow_displacement;
	t_screen_point				m_shadow_screen_point;
	t_screen_rect				m_shadow_view_rect;
	t_screen_rect				m_view_rect;
};

inline int t_abstract_combat_object::get_alpha() const
{
	return m_alpha;
}

inline long t_abstract_combat_object::get_battlefield_id() const
{
	// It is legal for m_battlefield_id to be zero (when there's no battle going on),
	// but in that case, nobody should be asking about it.
	assert( m_battlefield_id );

	return m_battlefield_id;
}

inline t_combat_object_iterator t_abstract_combat_object::get_list_position() 
{
	return m_list_position;
}

inline t_screen_point const& t_abstract_combat_object::get_shadow_screen_point() const
{
	return m_shadow_screen_point;
}


inline int t_abstract_combat_object::get_maximum_alpha() const
{
	return m_maximum_alpha;
}


inline t_screen_point const& t_abstract_combat_object::get_screen_position() const
{
	return m_screen_position;
}

inline t_screen_rect const& t_abstract_combat_object::get_shadow_view_rect() const
{
	return m_shadow_view_rect;
}

inline t_screen_rect const& t_abstract_combat_object::get_view_rect() const
{
	return m_view_rect;
}

inline bool t_abstract_combat_object::is_fading() const
{
	return m_fader != 0;
}

inline bool t_abstract_combat_object::is_on_draw_list() const
{
	return m_on_draw_list;
}

inline void t_abstract_combat_object::set_list_position( t_combat_object_iterator position )
{
	m_list_position = position;
}

inline void t_abstract_combat_object::set_maximum_alpha( int arg )
{
	m_maximum_alpha = arg;
}

inline void t_abstract_combat_object::set_on_draw_list( bool arg )
{
	m_on_draw_list = arg;
}

inline void t_abstract_combat_object::set_shadow_view_rect( t_screen_rect const& rect )
{
	m_shadow_view_rect = rect;
}

inline void t_abstract_combat_object::set_view_rect( t_screen_rect const& rect )
{
	m_view_rect = rect;
}

#endif // !defined( ABSTRACT_COMBAT_OBJECT_H_INCLUDED )
